home *** CD-ROM | disk | FTP | other *** search
- Path: fohnix.metronet.com!not-for-mail
- From: milam@fohnix.metronet.com (Stan Milam)
- Newsgroups: comp.lang.c
- Subject: Re: Comma Delimited function wanted
- Date: 18 Jan 1996 19:43:12 -0600
- Organization: Texas Metronet, Inc (login info (214/488-2590 - 817/571-0400))
- Message-ID: <4dmsvg$gqe@fohnix.metronet.com>
- References: <4d1l42$mb6@voyager.Internex.NET> <4d4gic$p7u@umbc9.umbc.edu> <4d6gi2$g4r@news.iag.net>
- NNTP-Posting-Host: fohnix.metronet.com
- X-Newsreader: TIN [version 1.2 PL2]
-
- John R Buchan (jatmon@iag.net) wrote:
- : In article <4d4gic$p7u@umbc9.umbc.edu>, schlein@umbc.edu says...
- : <snip>
- : >#include <stdio.h>
- : >
- : >int main (void)
- : >{
- : > char *buffer = "3740067099,914885AC2,P03,5000";
- : > char field1[20],
- : > field2[20],
- : > field3[20],
- : > field4[20];
- : >
- : > sscanf (buffer, "%[^,],%[^,],%[^,],%s", field1, field2, field3, field4);
- : > printf ("field1 = %s\n", field1);
- : > printf ("field2 = %s\n", field2);
- : > printf ("field3 = %s\n", field3);
- : > printf ("field4 = %s\n", field4);
- : >
- : > return (0);
- : >}
-
- : This works fine, unless it runs into something like:
-
- : char *buffer = "3740067099,,P03,5000";
-
- : A strtok based solution will have a similar problem. A full solution to
- : this type of parsing will require a non-standard function (custom code).
-
- Here are three custom code functions.
-
-
- /*FILE*****************************************************************/
- /* File Id: strptok.c. */
- /* Author: Stan Milam. */
- /* Date Written: 25-Apr-95. */
- /* Description: */
- /* Implement a strtok() like function which preserves the original*/
- /* string. */
- /* */
- /*****************************************************************FILE*/
-
- #include <stddef.h>
- #include <string.h>
-
- /*FUNCTION*************************************************************/
- /* Name: strptok(). */
- /* */
- /* Description: */
- /* This function implements a strtok() like function which pre- */
- /* serves the original string and copies tokens into a programmer */
- /* supplied buffer. */
- /* */
- /* Arguments: */
- /* char *dest - Address of buffer where token is to be copied. */
- /* char *src - Address of source buffer where tokens are to be */
- /* extracted. */
- /* char *brk - "Break" characters which delimit tokens. */
- /* */
- /* Return Value: */
- /* NULL when the end of the string is encounted or when the src */
- /* argument is NULL or empty. Otherwise the address just beyond */
- /* the last token found in the source string. */
- /* */
- /*************************************************************FUNCTION*/
-
- char *strptok( char *dest, char *src, char *brk ) {
-
- unsigned len;
- char *rv, *wrk;
-
- /******************************************************************/
- /* Make sure destination is empty and check for a valid source. */
- /******************************************************************/
-
- dest[0] = '\0';
- if ( src == NULL || *src == '\0' )
- rv = NULL;
-
- /******************************************************************/
- /* If there are not any break characters set rv to NULL and copy */
- /* the remaining characters to the destination. */
- /******************************************************************/
-
- else if (( wrk = strpbrk(src, brk) ) == NULL) {
- rv = NULL;
- strcpy( dest, src );
- }
-
- /******************************************************************/
- /* If the first character of source is a break character then */
- /* skip over it. */
- /******************************************************************/
-
- else if ( src == wrk )
- rv = src + 1;
-
- /******************************************************************/
- /* Found a token! Compute return value, length of token and copy */
- /* it to destination making sure it is null terminated. */
- /******************************************************************/
-
- else {
- rv = wrk + 1;
- len = wrk - src;
- strncpy( dest, src, len )[len] = '\0';
- }
- return rv;
- }
-
- #ifdef TEST
- #include <stdio.h>
- int main( void ) {
-
- char dest[50] = "", *rv;
- char *src = ":tsdsstm:243::0:Stan Milam,3730442330,Y:/u/tsdsstm/ksh";
-
- rv = strptok( dest, NULL, ":" );
- rv = strptok( dest, "", ":" );
-
- rv = strptok( dest, src, ":" );
- while ( rv || dest[0] ) {
- printf(":%s:\n", dest);
- rv = strptok( dest, rv, ":" );
- }
- }
- #endif
-
- /**********************************************************************/
- /* File Id: strparse.c. */
- /* Author: Stan Milam. */
- /* Date Written: 20-Feb-1995. */
- /* Description: */
- /* The str_parse() function is used to extract fields from de- */
- /* limited ASCII records. It is designed to deal with empty fields*/
- /* in a logical manner and meant to preclude the use of strtok() */
- /* for such purposes! */
- /* */
- /* Arguments: */
- /* char **str - The address of a pointer which in turn */
- /* points to the string being parsed. The */
- /* actual pointer is modified with each call to*/
- /* point to the beginning of the next field. */
- /* char *delimiters - The address of the string containing the */
- /* characters used to delimit the fields within*/
- /* the record. */
- /* */
- /* Return Value: */
- /* A pointer of type char which points to the current field in the*/
- /* parsed string. If an empty field is encountered the address */
- /* is that of an empty string (i.e. "" ). When there are no more */
- /* fields in the record a NULL pointer value is returned. */
- /* */
- /**********************************************************************/
-
- #include <stddef.h>
- #include <string.h>
-
- char *str_parse( char **str, char *delimiters ) {
-
- char *head, *tail, *rv;
-
- if ( *str == NULL || **str == '\0' )
- rv = NULL;
- else if ( delimiters == NULL || *delimiters == '\0' )
- rv = NULL;
- else {
- rv = head = *str;
- if ( ( tail = strpbrk( head, delimiters ) ) == NULL )
- *str = head + strlen( head );
- else {
- *tail = '\0';
- *str = tail + 1;
- }
- }
- return rv;
- }
-
- #ifdef TEST
- #include <stdio.h>
- #include <assert.h>
-
- int main( void ) {
-
- char *wrk, *rv;
- char delimiters[] = ":;";
- char wrkstr[] = "1:2::4:;6:7";
-
- wrk = "";
- assert( str_parse( NULL, delimiters ) == NULL );
- assert( str_parse( &wrk, delimiters ) == NULL );
-
- wrk = wrkstr;
- assert( str_parse( &wrk, NULL ) == NULL );
- assert( str_parse( &wrk, "" ) == NULL );
-
- while((rv = str_parse( &wrk, delimiters )))
- puts( rv );
-
- return 0;
- }
- #endif
-
-
- /**********************************************************************/
- /* File Id: strcut.c. */
- /* Author: Stan Milam. */
- /* Date Written: 5-Nov-94. */
- /* */
- /* ********************************************************************/
-
- #include <string.h>
- #include "toolbox.h"
-
- /**********************************************************************/
- /* Name: strcut() */
- /* */
- /* Description: */
- /* This function will surgically cut delimited fields from a */
- /* source string, placing the resulting string into a destination */
- /* address. All fields in the source string must be delimited by */
- /* the same character. A good example is the colon (:) delimited */
- /* fields in the /etc/passwd file in UNIX systems. */
- /* */
- /* Arguments: */
- /* char *dest - The destination address to place the re- */
- /* sulting string. */
- /* char *source - The string containing the delimited fields*/
- /* int delimiter - Character which delimites the fields. */
- /* unsigned field - The field to extract from source string. */
- /* */
- /* Return Value: */
- /* The address of the destination string. */
- /* */
- /**********************************************************************/
-
- char *strcut( char *dest, char *source, int delimiter, unsigned field ) {
-
- unsigned count, fld_max;
- char *wrk, *head, *tail;
-
- /******************************************************************/
- /* Count the number of delimiters. Then number of fields is al- */
- /* ways one more than the delimiters. */
- /******************************************************************/
-
- count = chrcount( source, delimiter );
- fld_max = count + 1;
-
- /******************************************************************/
- /* Do some sanity checks. Get out if there is no field, or no de- */
- /* limiter, or if we are going after a field that does not exist. */
- /******************************************************************/
-
- if ( (field == 0 || count == 0) || (field > fld_max) )
- *dest = '\0';
- else {
-
- /**************************************************************/
- /* Initialize our head pointer and using the delimiters work */
- /* our way to the field we want. */
- /**************************************************************/
-
- for ( head = source, count = 0; count < field; count++ ) {
- tail = head;
- wrk = strchr( head, delimiter );
-
- /**********************************************************/
- /* If we are on the last field we must point work at the */
- /* null character, else point head one character past the */
- /* current delimiter at the start of the next field. */
- /**********************************************************/
-
- if ( wrk == NULL ) wrk = head + strlen( head );
- else head = wrk + 1;
- }
-
- /**************************************************************/
- /* At this point wrk is at the end of the field and tail is at*/
- /* the beginning. Get number of characters between and copy. */
- /**************************************************************/
-
- count = ((unsigned) wrk) - ((unsigned) tail);
- strncpy( dest, tail, count )[count] = '\0';
- }
- return dest;
- }
-